import md5 from 'crypto-js/md5';
import dayjs from 'dayjs';
import client from 'mp-client-js';
import nprogress from 'nprogress';
import 'nprogress/nprogress.css';
import printJS from 'print-js';
import alert from './alert';
import './client.css';

const KEEP_ALIVE_INTERVAL = 600_000; // 10分钟

function parser(k, v) {
  // 识别ISO8601格式UTC时间，转换为dayjs类型
  if (typeof v === 'string' && v.length >= 19 && v.length <= 24 && /^(\d{4})-(\d{2})-(\d{2})/.test(v)) {
    const d = dayjs(v);
    return d.isValid() ? d : v;
  }
  return v;
}

let keep_alive_t;
function keep_alive() {
  if (keep_alive_t) {
    keep_alive_t = clearTimeout(keep_alive_t);
  }
  keep_alive_t = setTimeout(() => {
    client.job('B.TokenRenew').then(({ token }) => {
      client.setToken(token);
      keep_alive();
    });
  }, KEEP_ALIVE_INTERVAL);
}

const new_client = {
  ...client,

  getPage: async function (name) {
    nprogress.start();
    return window.MP.getPage(name).then(page => {
      nprogress.done();
      return page;
    }).catch(e => {
      nprogress.done();
      alert('开发包加载失败', e.message, { type: 'error' });
      throw e;
    });
  },

  /**
   * 初始化密码
   * @param {string} username 用户名
   * @param {string} password 密码
   * @returns Promise<any>
   */
  init_password: async function (username, password) {
    let key = String(md5(password + "@MP")).toLowerCase();
    return await client.job('B.PasswordInit', {
      User: username,
      Password: key
    });
  },

  /**
   * 修改密码
   * @param {string} old_password 旧密码
   * @param {string} new_password 新密码
   * @returns Promise<any>
   */
  change_password: async function (old_password, new_password) {
    let old_key = String(md5(old_password + "@MP")).toLowerCase();
    let new_key = String(md5(new_password + "@MP")).toLowerCase();
    return await client.job('B.PasswordChange', {
      OldPassword: old_key,
      NewPassword: new_key,
    });
  },

  /**
   * 使用用户名和密码获取token
   * @param {string} username 用户名
   * @param {string} password 密码
   * @returns Promise<{token,expires}>
   */
  login: async function (username, password = '') {
    let key = String(md5(password + "@MP")).toLowerCase();
    return await client.job(username ? 'B.LoginPwd' : 'B.TokenRenew',
      username ? {
        User: username,
        Password: key
      } : undefined).then((res) => {
        client.setToken(res.token);
        keep_alive();
        return res;
      });
  },

  /**
   * 销毁当前的token
   */
  logout: async function () {
    client.clearToken();
    keep_alive_t = clearTimeout(keep_alive_t);
  },

  _job: client.job,
  job: async (name, param, mute) => {
    nprogress.start();
    const res = client.job(name, param, parser).finally(nprogress.done);
    return mute ? res : res.catch(e => {
      alert('调用失败', e.message, { type: 'error' });
      return Promise.reject(e);
    });
  },

  guid: async (count = 1) => {
    const guids = client.get('guids') ?? [];
    if (guids.length < count) {
      const ids = await client.job('GetGUID', { Count: Math.max(count, 10) });
      guids.push(...ids);
      client.set('guids', guids);
    }
    return guids.slice(0, count);
  },

  _import: client.import,
  import: async (name, param, { validator = file => true, mute } = {}) => {
    const res = client.import(name, param, (file) => {
      if (validator(file)) {
        nprogress.start();
        return true;
      } else {
        return false;
      }
    }).finally(nprogress.done);
    return mute ? res : res.catch(e => {
      alert('导入失败', e.message, { type: 'error' });
      return Promise.reject(e);
    });
  },
  export_xls: async (name, param, { template, rename, mute } = {}) => {
    nprogress.start();
    const res = client.export.xls(name, param, template).then(d => {
      client.doc.download(d, rename);
    }).finally(nprogress.done);
    return mute ? res : res.catch(e => {
      alert('导出失败', e.message, { type: 'error' });
      return Promise.reject(e);
    });
  },
  export_pdf: async (name, param, { template, rename, mute } = {}) => {
    nprogress.start();
    const res = client.export.pdf(name, param, template).then(d => {
      client.doc.download(d, rename);
    }).finally(nprogress.done);
    return mute ? res : res.catch(e => {
      alert('导出失败', e.message, { type: 'error' });
      return Promise.reject(e);
    });
  },
  print: async (name, param, { template, mute } = {}) => {
    nprogress.start();
    const res = client.export.pdf(name, param, template).then(d => {
      return printJS(`/api/doc?file=${d}&access_token=${client.get('TOKEN')}`);
    }).finally(nprogress.done);
    return mute ? res : res.catch(e => {
      alert('调用失败', e.message, { type: 'error' });
      return Promise.reject(e);
    });
  },
};

export default new_client;